package com.chiga.interceptor;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.chiga.action.AbstractPagedAction;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class FilterMethodInterceptor extends AbstractInterceptor {

	private static final long serialVersionUID = -4514908962996379862L;
	private Map<String, Set<String>> include;
	private Map<String, Set<String>> exclude;

	@Override
	public String intercept(ActionInvocation ai) throws Exception {
		String action = ai.getProxy().getConfig().getClassName();
		String executeMethod = ai.getProxy().getMethod();

		if ("edit".equals(executeMethod)
				&& ai.getAction() instanceof AbstractPagedAction) {
			String oper = ((AbstractPagedAction) ai.getAction()).getOper();
			if ("edit".equals(oper)) {
				executeMethod = "save";
			} else if ("add".equals(oper)) {
				executeMethod = "add";
			} else if ("del".equals(oper)) {
				executeMethod = "delete";
			} else if ("batchEdit".equals(oper)) {
				executeMethod = "batchEdit";
			} else {
				throw new NoSuchMethodException(oper);
			}
		}
		
		if (exclude != null) {
			boolean pass = true;
			if (exclude.containsKey(action)) {
				if (exclude.get(action).contains(executeMethod)) {
					pass = false;
				}
			}

			if (pass && exclude.containsKey("")
					&& exclude.get("").contains(executeMethod)) {
				pass = false;
			}

			if (!pass) {
				throw new NoSuchMethodException(executeMethod);
			}
		}

		if (include != null) {
			boolean pass = false;
			if (include.containsKey(action)) {
				if (include.get(action).contains(executeMethod)) {
					pass = true;
				}
			}

			if (!pass && include.containsKey("")
					&& include.get("").contains(executeMethod)) {
				pass = true;
			}

			if (!pass) {
				throw new NoSuchMethodException(executeMethod);
			}
		}

		return ai.invoke();
	}

	public void setInclude(String param) {
		this.include = splitParameter(param);
	}

	public void setExclude(String param) {
		this.exclude = splitParameter(param);
	}

	private static Map<String, Set<String>> splitParameter(String param) {
		if (param == null)
			return null;
		Map<String, Set<String>> map = new HashMap<String, Set<String>>();

		String tmps[] = param.trim().split(",");
		boolean flag = false;
		String actionName = "";
		for (String tmp : tmps) {
			tmp = tmp.trim();
			int idx = -1;
			if ((idx = tmp.indexOf("[")) >= 0) {
				if (flag || tmp.indexOf("\\.") > 0)
					throw new IllegalArgumentException("參數格式不正確");
				flag = true;
				actionName = tmp.substring(0, idx).trim();
				tmp = tmp.substring(idx + 1).trim();
			}

			if ((idx = tmp.indexOf("]")) > 0) {
				if (!flag) {
					throw new IllegalArgumentException("參數格式不正確");
				} else {
					String value = tmp.substring(0, idx).trim();
					if (map.containsKey(actionName)) {
						map.get(actionName).add(value);
					} else {
						Set<String> set = new HashSet<String>();
						set.add(value);
						map.put(actionName, set);
						actionName = "";
					}
					flag = false;
					continue;
				}
			}

			if ((idx = tmp.indexOf(".")) >= 0) {
				String key = tmp.substring(0, idx).trim();
				String value = tmp.substring(idx + 1).trim();
				if (map.containsKey(key)) {
					map.get(key).add(value);
				} else {
					Set<String> set = new HashSet<String>();
					set.add(value);
					map.put(key, set);
				}
			} else {
				if (flag) {
					if (map.containsKey(actionName)) {
						map.get(actionName).add(tmp);
					} else {
						Set<String> set = new HashSet<String>();
						set.add(tmp);
						map.put(actionName, set);
					}
				} else {
					if (map.containsKey("")) {
						map.get("").add(tmp);
					} else {
						Set<String> set = new HashSet<String>();
						set.add(tmp);
						map.put("", set);
					}
				}
			}
		}

		return map;
	}
}
